home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / C Internet Config / IC Application Source ƒ / C Source ƒ / StandardGetFolder.c < prev   
Encoding:
C/C++ Source or Header  |  1995-12-01  |  10.7 KB  |  254 lines  |  [TEXT/SPM ]

  1. /******************************************************************************}
  2. { StandardGetFolder.c                                                          }
  3. {                                                                              }
  4. {    This little chunk o' code implements a way to let the user choose a       }
  5. {    folder to save files in via a StandardFile Dialog.                        }
  6. {                                                                              }
  7. {    Since the code uses the CustomGetFile function and depends on the use of  }
  8. {    FSSpec records, it only works under System 7.0 or later.                  }
  9. {                                                                              }
  10. {    And don't forget to include the custom dialog resources ( a 'DITL' and    }
  11. {   'DLOG') in your project.                                                   }
  12. {                                                                              }
  13. {    Portions of this code were originally provided by Paul Forrester          }
  14. {    (paulf@apple.com) to the think-c internet mailing list in response to my  }
  15. {    my question on how to do exactly what this code does.  I've added a       }
  16. {    couple of features, such as the ability to handle aliased folders and     }
  17. {    the programmer definable prompt.  I also cleaned and tightened the code,  }
  18. {    stomped a couple of bugs, and packaged it up neatly.  Bunches of work,    }
  19. {    but I learned A LOT about Standard File, the File Manager, the Dialog     }
  20. {    Manager, and the Alias Manager.  I tried to include in the comments some  }
  21. {    of the neat stuff I discovered in my hours of pouring over Inside Mac.    }
  22. {    Hope you find it educational as well as useful.                           }
  23. {******************************************************************************}
  24. { Converted to Pascal by Peter N Lewis <peter.lewis@info.curtin.edu.au> Dec 1992 }
  25.     
  26.     And back to C again (I didn't have the original C code and I didn't want to replace this with
  27.     work from another StandardGetFolder library. dhn.
  28. */
  29.  
  30. #include <Aliases.h>
  31. #include <Script.h>
  32. #include <TextUtils.h>
  33. #include <Types.h>
  34. #include <StandardFile.h>
  35. #include <LowMem.h>
  36.  
  37. #include "IC Misc Subs.h"
  38. #include "StandardGetFolder.h"
  39. #include "IC StandardFile.h"
  40.  
  41. // Global Variables
  42. Str255 gCurrentSelectedFolder;
  43.  
  44. // { The following set of routines are used to access a couple of low memory      }
  45. // { globals that are necessary when extending Standard File.  One example is     }
  46. // { trying to get the current directory while in a file filter.  These routines  }
  47. // { were used to bottleneck all the low memory usage.  If the system one day     }
  48. // { supports them with a trap call, then we can easily update these routines.    }
  49.  
  50. void GetSFLocation(short* vrn,long* dirID){
  51.     *vrn=-LMGetSFSaveDisk();
  52.     *dirID=LMGetCurDirStore();
  53. }
  54.  
  55. void SetSFLocation(short vrn,long dirID){
  56.     LMSetSFSaveDisk(-vrn);
  57.     LMSetCurDirStore(dirID);
  58. }
  59.  
  60. // {******************************************************************************}
  61. // { MyCustomGetDirectoryFileFilter                                               }
  62. // {                                                                              }
  63. // {     This is the file filter passed to CustomGetFile. It passes folders only. }
  64. // {******************************************************************************}
  65. pascal Boolean MyCustomGetDirectoryFileFilter(CInfoPBRec* myPB,Ptr myDataPtr){
  66.     Boolean dir,invis=false;
  67.     
  68.     dir=(myPB->hFileInfo.ioFlAttrib&16);
  69.     if (dir)
  70.         invis=(myPB->dirInfo.ioDrUsrWds.frFlags&0x4000);
  71.     
  72.     // return true to suppress, false to show
  73.     
  74.     return !((dir)&&(!(invis)));
  75. }
  76.  
  77.  
  78. // {******************************************************************************}
  79. // { MyCustomGetDirectoryDlogHook                                                 }
  80. // {                                                                              }
  81. // {     This function lets us process item hits in the GetFolderDialog.  We're   }
  82. // {     only interested if the user hit the selectFolder button. We pass all     }
  83. // {     other item hits back to ModalDialog.                                     }
  84. // {******************************************************************************}
  85.  
  86. void SetButtonTitle(DialogPtr theDialog,StringPtr name){
  87.     short resultCode;
  88.     short width;
  89.     Str255 TmpStr,left,right,bname;
  90.     short itemType;
  91.     Handle itemHandle;
  92.     Rect itemRect;
  93.     short p;
  94.     
  95.     // only if the names are not the same
  96.     if (IUEqualString(gCurrentSelectedFolder,name)){
  97.         GetDialogItem(theDialog,rGetFolderSelectString,&itemType,&itemHandle,&itemRect);
  98.         GetDialogItemText(itemHandle,TmpStr);
  99.         
  100.         p=TPPos("\p^1",TmpStr);
  101.         
  102.         // p points at the ^1
  103.         TPCopy(left,TmpStr,1,p-1);
  104.         TPCopy(right,TmpStr,p+2,255);
  105.         
  106.         GetDialogItem(theDialog,rGetFolderButton,&itemType,&itemHandle,&itemRect);
  107.         
  108.         SetPString(gCurrentSelectedFolder,1,name);
  109.         
  110. //     {*-------------------------------------------------------------------------}
  111. //     { Find the width left over in the button after drawing the word 'Select'   }
  112. //     { the quotation marks. Truncate the new name to this length.               }
  113. //     {-------------------------------------------------------------------------*}
  114.         
  115.         SetPString(bname,4,"\p ",left,right,"\p ");
  116.         
  117.         width=(itemRect.right-itemRect.left)-StringWidth(bname);
  118.         resultCode=TruncString(width,name,smTruncEnd);
  119.         
  120.         // add the name to the temp str
  121.         SetPString(TmpStr,3,left,name,right);
  122.         
  123.         SetControlTitle((ControlHandle)itemHandle,TmpStr);
  124.         ValidRect(&itemRect);
  125.     }
  126. }
  127.  
  128. void SetFolderButtonTitle(DialogPtr dlg,short vrn,long dirID){
  129.     Str63 name;
  130.     CInfoPBRec pb;
  131.     OSErr oe;
  132.     
  133.     pb.hFileInfo.ioNamePtr=name;
  134.     pb.hFileInfo.ioVRefNum=vrn;
  135.     pb.hFileInfo.ioDirID=dirID;
  136.     pb.hFileInfo.ioFDirIndex=-1;
  137.     
  138.     if (PBGetCatInfoSync(&pb)==noErr)
  139.         SetButtonTitle(dlg,name);
  140. }
  141.  
  142. pascal short MyCustomGetDirectoryDlogHook(short item,DialogPtr theDialog,Ptr myDataPtr){
  143.     short itemType;
  144.     Rect itemRect;
  145.     Handle itemHandle;
  146.     StandardFileReplyPtr mySFRPtr;
  147.     
  148. //     {*-------------------------------------------------------------------------}
  149. //     { CustomGet calls dialog hook for both main and subsidiary dialog boxes.   }
  150. //     { Make sure that dialog record indicates that this is the main GetFolder   }
  151. //     { dialog.                                                                  }
  152. //     {-------------------------------------------------------------------------*}
  153.     
  154.     if (((OSType)((WindowPeek)theDialog)->refCon)==sfMainDialogRefCon){
  155.         mySFRPtr=(StandardFileReplyPtr)myDataPtr;
  156.         
  157.         if (item==sfHookFirstCall){
  158. //             {*-----------------------------------------------------------------}
  159. //             { Set the prompt displayed above the file list...                  }
  160. //             {-----------------------------------------------------------------*}
  161.             GetDialogItem(theDialog,rGetFolderMessage,&itemType,&itemHandle,&itemRect);
  162.             SetDialogItemText(itemHandle,gCurrentSelectedFolder);
  163.             gCurrentSelectedFolder[0]=0;
  164.         } else {
  165.             if (mySFRPtr->sfFile.name[0]==0){
  166.                 GetSFLocation(&(mySFRPtr->sfFile.vRefNum),&(mySFRPtr->sfFile.parID));
  167.                 mySFRPtr->sfFile.name[0]=0;
  168.                 SetFolderButtonTitle(theDialog,mySFRPtr->sfFile.vRefNum,mySFRPtr->sfFile.parID);
  169.             } else {
  170.                 SetButtonTitle(theDialog,mySFRPtr->sfFile.name);
  171.             }
  172.         }
  173.         
  174.         if (item==rGetFolderButton){
  175.             item=sfItemCancelButton;
  176.             mySFRPtr->sfGood=true;
  177.         }
  178.     }
  179.     return item;
  180. }
  181.  
  182. // {******************************************************************************}
  183. // { StandardGetFolder                                                            }
  184. // {                                                                              }
  185. // {     The StandardGetFolder function. You pass it the point where you want the }
  186. // {     standard file dialog box drawn, the prompt to display above the file     }
  187. // {     list, and a pointer to an StandardFileReply record.                      }
  188. // {                                                                              }
  189. // {     Upon return, the sfFile field of the SFReply record contains the volume  }
  190. // {     reference number and directory ID that specify the folder the user       }
  191. // {     chose. It also passes back the name of the chosen folder.  The sfGood    }
  192. // {     field is set to true if the user chose a folder, or false if not.        }
  193. // {******************************************************************************}
  194.  
  195. void StandardGetFolder(Point where,StringPtr message,StandardFileReply* mySFReply){
  196.     SFTypeList theTypeList;
  197.     CInfoPBRec pb;
  198.     Boolean isfolder,wasaliased;
  199.     OSErr oe;
  200.     
  201. //     {*-------------------------------------------------------------------------}
  202. //     { Copy the prompt to be displayed above the file list into gCurrentSelectedFolder  }
  203. //     { When MyCustomGetDirectoryDlogHook is called for   }
  204. //     { the first time, it will use this info to draw the prompt.                }
  205. //     {-------------------------------------------------------------------------*}
  206.     SetPString(gCurrentSelectedFolder,1,message);
  207.  
  208. //     {*-------------------------------------------------------------------------}
  209. //     { Call CustomGetFile. Pass it a pointer to the file filter and dialog      }
  210. //     { hook functions. Also pass a pointer to mySFReply in the user data field. }
  211. //     {-------------------------------------------------------------------------*}
  212.     
  213.     CustomGetFile(gMyCustomGetDirectoryFileFilter,-1,theTypeList,mySFReply,rGetFolderDialog,
  214.         where,gMyCustomGetDirectoryDlogHook,
  215.         (ModalFilterYDUPP)0,(short*)0,(ActivateYDUPP)0,(void*)mySFReply);
  216.  
  217. //     {*-------------------------------------------------------------------------}
  218. //     { Ok, now the reply record contains the volume reference number and the    }
  219. //     { name of the selected folder. We need to use PBGetCatInfo to get the      }
  220. //     { directory ID of the selected folder.                                     }
  221. //     {-------------------------------------------------------------------------*}
  222.     if (mySFReply->sfGood){ //{ Don't call PBGetCatInfo on cancel! }
  223.  
  224.         if (mySFReply->sfFile.name[0]!=0){
  225.             oe=ResolveAliasFile(&(mySFReply->sfFile), true,&isfolder,&wasaliased);
  226.             if ((oe==noErr)&&(!isfolder)){
  227.                 // not a folder, weird error here
  228.             }
  229.             if (oe==noErr){
  230.                 pb.hFileInfo.ioVRefNum=mySFReply->sfFile.vRefNum;
  231.                 pb.hFileInfo.ioDirID=mySFReply->sfFile.parID;
  232.                 pb.hFileInfo.ioNamePtr=mySFReply->sfFile.name;
  233.                 pb.hFileInfo.ioFDirIndex=0;
  234.                 
  235.                 oe=PBGetCatInfoSync(&pb);
  236.             }
  237.             
  238.             mySFReply->sfGood=(oe==noErr);
  239.             mySFReply->sfFile.parID=pb.dirInfo.ioDrDirID;
  240.             mySFReply->sfFile.name[0]=0;
  241.         }
  242.         
  243.         if (oe==noErr){
  244.             pb.hFileInfo.ioVRefNum=mySFReply->sfFile.vRefNum;
  245.             pb.hFileInfo.ioDirID=mySFReply->sfFile.parID;
  246.             pb.hFileInfo.ioNamePtr=mySFReply->sfFile.name;
  247.             pb.hFileInfo.ioFDirIndex=-1;
  248.             
  249.             oe=PBGetCatInfoSync(&pb);
  250.         }
  251.     }
  252. }
  253.  
  254.